LIBECAL_MIN_VERSION=2.32.0
LIBEDATASERVER_MIN_VERSION=1.2.0
LIBEDATASERVERUI_MIN_VERSION=2.91.6
-TELEPATHY_GLIB_MIN_VERSION=0.13.12
+TELEPATHY_GLIB_MIN_VERSION=0.15.0
TELEPATHY_LOGGER_MIN_VERSION=0.2.4
POLKIT_MIN_VERSION=0.100
STARTUP_NOTIFICATION_MIN_VERSION=0.11
// The second argument, recover, means _observeChannels will be run
// for any existing channel as well.
let dbus = Tp.DBusDaemon.dup();
- this._observer = Shell.TpClient.new(dbus);
- this._observer.set_observe_channels_func(
+ this._tp_client = new Shell.TpClient({ 'dbus_daemon': dbus,
+ 'name': 'GnomeShell',
+ 'uniquify-name': true })
+ this._tp_client.set_observe_channels_func(
Lang.bind(this, this._observeChannels));
+ this._tp_client.set_approve_channels_func(
+ Lang.bind(this, this._approveChannels));
+ this._tp_client.set_handle_channels_func(
+ Lang.bind(this, this._handleChannels));
try {
- this._observer.register();
+ this._tp_client.register();
} catch (e) {
- throw new Error('Couldn\'t register SimpleObserver. Error: \n' + e);
+ throw new Error('Couldn\'t register Telepathy client. Error: \n' + e);
}
},
if (this._sources[channel.get_object_path()])
return;
- let source = new Source(account, conn, channel, contact);
+ let source = new Source(account, conn, channel, contact, this._tp_client);
this._sources[channel.get_object_path()] = source;
source.connect('destroy', Lang.bind(this,
function() {
+ if (this._tp_client.is_handling_channel(channel)) {
+ // The chat box has been destroyed so it can't
+ // handle the channel any more.
+ channel.close_async(null);
+ }
+
delete this._sources[channel.get_object_path()];
}));
+ },
+
+ _handlingChannels: function(account, conn, channels) {
+ let len = channels.length;
+ for (let i = 0; i < len; i++) {
+ let channel = channels[i];
+
+ // We can only handle text channel, so close any other channel
+ if (!(channel instanceof Tp.TextChannel)) {
+ channel.close_async(null);
+ continue;
+ }
+
+ if (this._tp_client.is_handling_channel(channel)) {
+ // We are already handling the channel, display the source
+ let source = this._sources[channel.get_object_path()];
+ if (source)
+ source.notify();
+ }
+ }
+ },
+
+ _approveChannels: function(approver, account, conn, channels,
+ dispatchOp, context) {
+ // Approve the channels right away as we are going to handle it
+ dispatchOp.claim_with_async(this._tp_client,
+ Lang.bind (this, function(dispatchOp, result) {
+ try {
+ dispatchOp.claim_with_finish(result);
+ this._handlingChannels(account, conn, channels);
+ } catch (err) {
+ global.logError('Failed to Claim channel: ' + err);
+ }}));
+
+ context.accept();
+ },
+
+ _handleChannels: function(handler, account, conn, channels,
+ requests, user_action_time, context) {
+ this._handlingChannels(account, conn, channels);
+ context.accept();
}
};
-function Source(account, conn, channel, contact) {
- this._init(account, conn, channel, contact);
+function Source(account, conn, channel, contact, client) {
+ this._init(account, conn, channel, contact, client);
}
Source.prototype = {
__proto__: MessageTray.Source.prototype,
- _init: function(account, conn, channel, contact) {
+ _init: function(account, conn, channel, contact, client) {
MessageTray.Source.prototype._init.call(this, contact.get_alias());
this.isChat = true;
this._account = account;
this._contact = contact;
+ this._client = client;
this._conn = conn;
this._channel = channel;
},
open: function(notification) {
- let props = {};
- props[Tp.PROP_CHANNEL_CHANNEL_TYPE] = Tp.IFACE_CHANNEL_TYPE_TEXT;
- [props[Tp.PROP_CHANNEL_TARGET_HANDLE], props[Tp.PROP_CHANNEL_TARGET_HANDLE_TYPE]] = this._channel.get_handle();
-
- let req = Tp.AccountChannelRequest.new(this._account, props, global.get_current_time());
-
- req.ensure_channel_async('', null, null);
+ if (this._client.is_handling_channel(this._channel)) {
+ // We are handling the channel, try to pass it to Empathy
+ this._client.delegate_channels_async([this._channel], global.get_current_time(), "", null);
+ }
+ else {
+ // We are not the handler, just ask to present the channel
+ let dbus = Tp.DBusDaemon.dup();
+ let cd = Tp.ChannelDispatcher.new(dbus);
+
+ cd.present_channel_async(this._channel, global.get_current_time(), null);
+ }
},
_getLogMessages: function() {
ShellTpClientObserveChannelsImpl observe_impl;
gpointer user_data_obs;
GDestroyNotify destroy_obs;
+
+ ShellTpClientApproveChannelsImpl approve_channels_impl;
+ gpointer user_data_approve_channels;
+ GDestroyNotify destroy_approve_channels;
+
+ ShellTpClientHandleChannelsImpl handle_channels_impl;
+ gpointer user_data_handle_channels;
+ GDestroyNotify destroy_handle_channels;
};
/**
* Signature of the implementation of the ObserveChannels method.
*/
+/**
+ * ShellTpClientApproveChannelsImpl:
+ * @client: a #ShellTpClient instance
+ * @account: a #TpAccount having %TP_ACCOUNT_FEATURE_CORE prepared if possible
+ * @connection: a #TpConnection having %TP_CONNECTION_FEATURE_CORE prepared
+ * if possible
+ * @channels: (element-type TelepathyGLib.Channel): a #GList of #TpChannel,
+ * all having %TP_CHANNEL_FEATURE_CORE prepared if possible
+ * @dispatch_operation: (allow-none): a #TpChannelDispatchOperation or %NULL;
+ * the dispatch_operation is not guaranteed to be prepared
+ * @context: a #TpAddDispatchOperationContext representing the context of this
+ * D-Bus call
+ *
+ * Signature of the implementation of the AddDispatchOperation method.
+ */
+
+/**
+ * ShellTpClientHandleChannelsImpl:
+ * @client: a #ShellTpClient instance
+ * @account: a #TpAccount having %TP_ACCOUNT_FEATURE_CORE prepared if possible
+ * @connection: a #TpConnection having %TP_CONNECTION_FEATURE_CORE prepared
+ * if possible
+ * @channels: (element-type TelepathyGLib.Channel): a #GList of #TpChannel,
+ * all having %TP_CHANNEL_FEATURE_CORE prepared if possible
+ * @requests_satisfied: (element-type TelepathyGLib.ChannelRequest): a #GList of
+ * #TpChannelRequest having their object-path defined but are not guaranteed
+ * to be prepared.
+ * @user_action_time: the time at which user action occurred, or one of the
+ * special values %TP_USER_ACTION_TIME_NOT_USER_ACTION or
+ * %TP_USER_ACTION_TIME_CURRENT_TIME
+ * (see #TpAccountChannelRequest:user-action-time for details)
+ * @context: a #TpHandleChannelsContext representing the context of this
+ * D-Bus call
+ *
+ * Signature of the implementation of the HandleChannels method.
+ */
+
static void
shell_tp_client_init (ShellTpClient *self)
{
+ GHashTable *filter;
+
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SHELL_TYPE_TP_CLIENT,
ShellTpClientPrivate);
+ /* We only care about single-user text-based chats */
+ filter = tp_asv_new (
+ TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
+ TP_IFACE_CHANNEL_TYPE_TEXT,
+ TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
+ TP_HANDLE_TYPE_CONTACT,
+ NULL);
+
/* Observer */
tp_base_client_set_observer_recover (TP_BASE_CLIENT (self), TRUE);
- /* We only care about single-user text-based chats */
- tp_base_client_take_observer_filter (TP_BASE_CLIENT (self),
- tp_asv_new (
- TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
- TP_IFACE_CHANNEL_TYPE_TEXT,
- TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
- TP_HANDLE_TYPE_CONTACT,
- NULL));
+ tp_base_client_add_observer_filter (TP_BASE_CLIENT (self), filter);
+
+ /* Approver */
+ tp_base_client_add_approver_filter (TP_BASE_CLIENT (self), filter);
+
+ /* Handler */
+ tp_base_client_add_handler_filter (TP_BASE_CLIENT (self), filter);
+
+ g_hash_table_unref (filter);
}
static void
dispatch_operation, requests, context, self->priv->user_data_obs);
}
+static void
+add_dispatch_operation (TpBaseClient *client,
+ TpAccount *account,
+ TpConnection *connection,
+ GList *channels,
+ TpChannelDispatchOperation *dispatch_operation,
+ TpAddDispatchOperationContext *context)
+{
+ ShellTpClient *self = (ShellTpClient *) client;
+
+ g_assert (self->priv->approve_channels_impl != NULL);
+
+ self->priv->approve_channels_impl (self, account, connection, channels,
+ dispatch_operation, context, self->priv->user_data_approve_channels);
+}
+
+static void
+handle_channels (TpBaseClient *client,
+ TpAccount *account,
+ TpConnection *connection,
+ GList *channels,
+ GList *requests_satisfied,
+ gint64 user_action_time,
+ TpHandleChannelsContext *context)
+{
+ ShellTpClient *self = (ShellTpClient *) client;
+
+ g_assert (self->priv->handle_channels_impl != NULL);
+
+ self->priv->handle_channels_impl (self, account, connection, channels,
+ requests_satisfied, user_action_time, context,
+ self->priv->user_data_handle_channels);
+}
+
static void
shell_tp_client_dispose (GObject *object)
{
{
self->priv->destroy_obs (self->priv->user_data_obs);
self->priv->destroy_obs = NULL;
+ self->priv->user_data_obs = NULL;
+ }
+
+ if (self->priv->destroy_approve_channels != NULL)
+ {
+ self->priv->destroy_approve_channels (self->priv->user_data_approve_channels);
+ self->priv->destroy_approve_channels = NULL;
+ self->priv->user_data_approve_channels = NULL;
+ }
+
+ if (self->priv->destroy_handle_channels != NULL)
+ {
+ self->priv->destroy_handle_channels (self->priv->user_data_handle_channels);
+ self->priv->destroy_handle_channels = NULL;
+ self->priv->user_data_handle_channels = NULL;
}
if (dispose != NULL)
object_class->dispose = shell_tp_client_dispose;
base_clt_cls->observe_channels = observe_channels;
-}
-
-/**
- * shell_tp_client_new:
- * @dbus: a #TpDBusDaemon object, may not be %NULL
- *
- * Returns: a new #ShellTpClient
- */
-ShellTpClient *
-shell_tp_client_new (TpDBusDaemon *dbus)
-{
- return g_object_new (SHELL_TYPE_TP_CLIENT,
- "dbus-daemon", dbus,
- "name", "GnomeShell",
- "uniquify-name", TRUE,
- NULL);
+ base_clt_cls->add_dispatch_operation = add_dispatch_operation;
+ base_clt_cls->handle_channels = handle_channels;
}
void
self->priv->destroy_obs = destroy;
}
+void
+shell_tp_client_set_approve_channels_func (ShellTpClient *self,
+ ShellTpClientApproveChannelsImpl approve_channels_impl,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ g_assert (self->priv->approve_channels_impl == NULL);
+
+ self->priv->approve_channels_impl = approve_channels_impl;
+ self->priv->user_data_approve_channels = user_data;
+ self->priv->destroy_approve_channels = destroy;
+}
+
+void
+shell_tp_client_set_handle_channels_func (ShellTpClient *self,
+ ShellTpClientHandleChannelsImpl handle_channels_impl,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ g_assert (self->priv->handle_channels_impl == NULL);
+
+ self->priv->handle_channels_impl = handle_channels_impl;
+ self->priv->user_data_handle_channels = user_data;
+ self->priv->destroy_handle_channels = destroy;
+}
+
/* Telepathy utility functions */
/**
TpObserveChannelsContext *context,
gpointer user_data);
-ShellTpClient * shell_tp_client_new (TpDBusDaemon *dbus);
-
void shell_tp_client_set_observe_channels_func (ShellTpClient *self,
ShellTpClientObserveChannelsImpl observe_impl,
gpointer user_data,
GDestroyNotify destroy);
+typedef void (*ShellTpClientApproveChannelsImpl) (
+ ShellTpClient *client,
+ TpAccount *account,
+ TpConnection *connection,
+ GList *channels,
+ TpChannelDispatchOperation *dispatch_operation,
+ TpAddDispatchOperationContext *context,
+ gpointer user_data);
+
+void shell_tp_client_set_approve_channels_func (ShellTpClient *self,
+ ShellTpClientApproveChannelsImpl approve_impl,
+ gpointer user_data,
+ GDestroyNotify destroy);
+
+typedef void (*ShellTpClientHandleChannelsImpl) (
+ ShellTpClient *client,
+ TpAccount *account,
+ TpConnection *connection,
+ GList *channels,
+ GList *requests_satisfied,
+ gint64 user_action_time,
+ TpHandleChannelsContext *context,
+ gpointer user_data);
+
+void shell_tp_client_set_handle_channels_func (ShellTpClient *self,
+ ShellTpClientHandleChannelsImpl handle_channels_impl,
+ gpointer user_data,
+ GDestroyNotify destroy);
+
/* Telepathy utility functions */
typedef void (*ShellGetTpContactCb) (TpConnection *connection,
GList *contacts,